<template>
  <a-card
    :bordered="false"
    :head-style="{ textAlign: 'right' }"
    :body-style="{ height: 'calc(100vh - 120px - 50px)', overflowY: 'auto' }"
    @contextmenu.prevent.stop="showContextMenu($event, null)"
    @paste="handlePaste"
  >
    <template #title>
      <a-button type="text" status="danger" @click="cleanAll">清空</a-button>
    </template>
    <a-row class="form_chunk table-page-search-wrapper">
      <a-form
        :layout="
          dataObj.allFormConfig.labelAlign !== 'horizontal'
            ? 'inline'
            : 'horizontal'
        "
        :label-align="
          dataObj.allFormConfig.labelAlign === 'horizontal'
            ? 'left'
            : dataObj.allFormConfig.labelAlign
        "
        :label-col-props="{ span: labelCol.span }"
        :label-col-style="labelCol.style"
        :wrapper-col-props="wrapperCol"
      >
        <draggable
          :list="dataObj.pageData"
          item-key="cid"
          :group="group"
          class="draggable_chunk arco-row"
          :scroll="true"
          :forceFallback="true"
          delay="50"
          animation="300"
          ghostClass="ghostClass"
          @change="homeChange"
        >
          <template #item="{ element, index }">
            <a-col
              :key="element.cid"
              class="column_chunk"
              :class="{ active: dataObj.selectIndex == index }"
              @click="itemClick(index)"
              :span="element.formData.wrapperCol"
              @contextmenu.prevent.stop="showContextMenu($event, index)"
            >
              <span
                v-if="dataObj.selectIndex == index"
                class="copy_icon"
                @click.stop="copyClick(index, element)"
                >复制</span
              >
              <span
                v-if="dataObj.selectIndex == index"
                class="delete_icon"
                @click="deleteClick(element)"
                >删除</span
              >
              <component
                :class="{ hoverBox: true, show: element.formData.hide }"
                :is="componentType(element.type)"
                :formData="element.formData"
                ref="dragViews"
              />
            </a-col>
          </template>
        </draggable>
      </a-form>
    </a-row>
    <!-- 右键菜单   -->
    <context-menu ref="contextMenu"></context-menu>
  </a-card>
</template>

<script>
import { Modal, Message } from "@arco-design/web-vue";
import draggable from "vuedraggable";
import InputInfo from "@/components/Form/dragViews/InputInfo.vue";
import SelectInfo from "@/components/Form/dragViews/SelectInfo.vue";
import RadioInfo from "@/components/Form/dragViews/RadioInfo.vue";
import UploadInfo from "@/components/Form/dragViews/UploadInfo.vue";
import DatePickerInfo from "@/components/Form/dragViews/DatePickerInfo.vue";
import TextareaInfo from "@/components/Form/dragViews/TextareaInfo.vue";
import InputNumberInfo from "@/components/Form/dragViews/InputNumberInfo.vue";
import CheckboxInfo from "@/components/Form/dragViews/CheckboxInfo.vue";
import SwitchInfo from "@/components/Form/dragViews/SwitchInfo.vue";
import TimePickerInfo from "@/components/Form/dragViews/TimePickerInfo.vue";
import DividerInfo from "@/components/Form/dragViews/DividerInfo.vue";
import KeyValueInputInfo from "@/components/Form/dragViews/KeyValueInputInfo.vue";
import DivModelInfo from "@/components/Form/dragViews/DivModelInfo.vue";
import EditorInfo from "@/components/Form/dragViews/EditorInfo.vue";
import TreeInfo from "@/components/Form/dragViews/TreeInfo.vue";
import CountFormulaInfo from "@/components/Form/dragViews/CountFormulaInfo.vue";
import TableInfo from "@/components/Form/dragViews/TableInfo.vue";
import CascaderInfo from "@/components/Form/dragViews/CascaderInfo.vue";
import TimelineInfo from "@/components/Form/dragViews/TimelineInfo.vue";
import TreeSelectInfo from "@/components/Form/dragViews/TreeSelectInfo.vue";

import { nanoid } from "nanoid";
import _ from "lodash";
import {
  componentTypeFileName,
  basicDefaultData,
} from "@/components/Form/base/options";
import ContextMenu from "@/components/Form/base/ContextMenu.vue";

export default {
  name: "FormPage",
  computed: {
    labelCol() {
      return {
        span: 4,
        style: { width: this.dataObj.allFormConfig.labelWidth + "px" },
      };
    },
  },
  components: {
    ContextMenu,
    draggable,
    InputInfo,
    SelectInfo,
    RadioInfo,
    UploadInfo,
    DatePickerInfo,
    TextareaInfo,
    InputNumberInfo,
    CheckboxInfo,
    SwitchInfo,
    TimePickerInfo,
    DividerInfo,
    KeyValueInputInfo,
    DivModelInfo,
    EditorInfo,
    TreeInfo,
    CountFormulaInfo,
    TableInfo,
    CascaderInfo,
    TimelineInfo,
    TreeSelectInfo,
  },
  data() {
    return {
      wrapperCol: { span: 24 },
      group: {
        name: "fitment",
        pull: false, // 可以拖出
        put: true, // 可以拖入
      },
    };
  },
  inject: ["dataObj"],
  methods: {
    componentType(value) {
      return componentTypeFileName[value];
    },
    pasterContent: ContextMenu.methods.pasterContent,
    handlePaste(event) {
      const text = (event.clipboardData || window.clipboardData).getData(
        "text"
      );
      this.pasterContent(text);
    },
    showContextMenu(event, index) {
      if (index !== null) {
        this.dataObj.selectIndex = index; // 右键选中组件
      }
      this.$refs.contextMenu.show(event, index);
    },
    // 保存内容
    handleSave() {
      console.log("保存内容");
      const { pageData } = this.dataObj;
      const sendData = {
        pageData,
      };
      const viewUi = JSON.stringify(sendData);
      // 将画布JSON保存到 dataObj.viewUi，供上层提交
      this.dataObj.viewUi = viewUi;
      console.log(viewUi);
    },
    homeChange(e) {
      // 拖拽或移动事件
      console.log("拖拽发生变化内容", e);
      if (e.added) {
        // 新增
        const { element, newIndex } = e.added;
        // 使用深拷贝替换自动插入的占位，避免引用共享
        const data = _.cloneDeep(element);
        if (!data.cid) data.cid = nanoid();
        // 默认表单属性，避免多个同类控件共享引用
        if (!data.formData || Object.keys(data.formData).length === 0) {
          data.formData = { ...basicDefaultData() };
        }
        // 一行两列模板展开为两个输入框
        if (data.type === "rowTwo") {
          const left = _.cloneDeep({
            ...data,
            type: "input",
            cid: nanoid(),
            formData: { ...basicDefaultData(), wrapperCol: 12 },
          });
          const right = _.cloneDeep({
            ...data,
            type: "input",
            cid: nanoid(),
            formData: { ...basicDefaultData(), wrapperCol: 12 },
          });
          // 删除自动插入的占位
          this.dataObj.pageData.splice(newIndex, 1, left, right);
          this.dataObj.selectIndex = newIndex;
          return;
        }
        // 普通组件：用深拷贝替换掉自动插入的原对象
        this.dataObj.pageData.splice(newIndex, 1, data);
        this.dataObj.selectIndex = newIndex;
      } else {
        // 移动位置：vuedraggable 已自动更新 :list，这里只需同步选中索引，避免二次 splice 导致数据错乱
        const { newIndex } = e.moved;
        this.dataObj.selectIndex = newIndex;
      }
    },
    onInput(e) {
      console.log("检查输出", e);
    },
    // 复制组件
    copyClick(index, item) {
      const data = _.cloneDeep(item);
      data.cid = nanoid();
      data.formData.notMod = false;
      this.dataObj.pageData.splice(index + 1, 0, data);
      console.log(this.dataObj.selectIndex);
      this.dataObj.selectIndex = this.dataObj.pageData.findIndex(
        (item) => item.cid === data.cid
      );
    },
    // 点击某个组件
    itemClick(index) {
      this.dataObj.selectIndex = index;
    },
    // 清空组件
    cleanAll() {
      Modal.confirm({
        title: "提示",
        content: "确定清除所有组件吗？",
        okText: "确认",
        cancelText: "取消",
        onOk: () => {
          this.dataObj.pageData.splice(0, this.dataObj.pageData.length);
          this.dataObj.selectIndex = undefined;
        },
        onCancel: () => {},
      });
    },
    // 删除组件
    deleteClick(record) {
      const index = this.dataObj.pageData.findIndex(
        (e) => e.cid === record.cid
      );
      Modal.confirm({
        title: "提示",
        content: "确定删除该组件吗？",
        okText: "确认",
        cancelText: "取消",
        onOk: () => {
          // 判断是否已关联外键 是则不能删除
          const tableEx = Array.isArray(this.dataObj.tableExConfig)
            ? this.dataObj.tableExConfig
            : [];
          const hasExTable = tableEx.some(
            (item) =>
              Array.isArray(item?.data) &&
              item.data.some((e) => e.cid === record.cid)
          );
          if (hasExTable) {
            // 存在关联外键不能删除
            Message.warning("已关联外键，请先删除外键关系");
            return;
          }
          this.dataObj.pageData.splice(index, 1);
          this.dataObj.selectIndex = undefined;
        },
        onCancel: () => {},
      });
    },
  },
};
</script>

<style lang="less" scoped>
.hoverBox.show {
  position: relative;
}

.hoverBox.show::after {
  content: "隐藏";
  font-size: 12px;
  position: absolute;
  top: 4px;
  right: 4px;
  padding: 4px 8px;
  background-color: #c6c6c6;
  color: #fff;
  border-radius: 50px;
}

.form_chunk {
  height: 100%;
  overflow-y: auto;
  padding-bottom: 20px;
  background: #ffffff;
  &.form_mobile {
    width: 378px;
    height: 770px;
    overflow-y: auto;
    background-size: 378px 770px;
    padding: 110px 10px 100px 10px;
    display: flex;
    justify-content: center;
    margin: 0 auto;
    background-image: url("./images/form_mobile.png");
    .form_mobile_info {
      overflow-y: auto;
      height: 555px;
    }
  }
  .draggable_chunk {
    width: 100%;
    padding-bottom: 30px;
    /deep/ .info_chunk {
      padding: 0 10px;
      min-height: 55.5px;
    }
  }
  .column_chunk {
    // border: dashed 2px #999999;
    border: dashed 2px transparent;
    border-radius: 15px;
    //margin-left: 5px;
    position: relative;
    .copy_icon {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      background: #ecf5ff;
      color: #409eff;
      border: 1px solid #b3d8ff;
      font-size: 16px;
      display: flex;
      justify-content: center;
      align-items: center;
      position: absolute;
      z-index: 10;
      right: 55px;
      bottom: -20px;
    }
    .delete_icon {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      background: #fef0f0;
      color: #f56c6c;
      border: 1px solid #fbc4c4;
      font-size: 16px;
      display: flex;
      justify-content: center;
      align-items: center;
      position: absolute;
      z-index: 10;
      right: 10px;
      bottom: -20px;
    }
  }
  .column_chunk.active {
    border: solid 2px #1890ff;
    border-radius: 15px;
  }
  .item_chunk {
    width: 94%;
    min-height: 60px;
    border: solid 2px transparent;
    border-radius: 15px;
    margin: 0 auto;
    overflow: hidden;
    position: relative;
    padding: 5px;
    margin-bottom: 10px;
    box-sizing: border-box;
  }
  .item_chunk.active {
    border: solid 2px #1890ff;
    border-radius: 15px;
  }
  .userInfo {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding-top: 40px;
    .userImage {
      width: 70px;
      height: 70px;
      background: #f0f1f3;
      border-radius: 50%;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      img {
        display: inline-block;
        width: 62px;
        height: 62px;
        border-radius: 50%;
        object-fit: cover;
      }
    }
    .user-name {
      padding-top: 20px;
      font-size: 16px;
      color: #1a1a1a;
    }
  }
}
.ghostClass {
  // background-color: #000 !important;
  // color: #fff;
  //width: 100% !important;
  height: 110px !important;
  border: dashed 2px #1890ff !important;
  border-radius: 15px !important;
  margin: 0 auto;
  div,
  img {
    display: none !important;
  }
}
.ghostClass::after {
  content: "我要放在这里～";
  display: inline-flex;
  width: 100% !important;
  height: 100% !important;
  justify-content: center;
  align-items: center;
}
/deep/ .arco-form-item {
  margin-bottom: 0;
  padding: 10px;
}

/deep/ ::-webkit-scrollbar {
  display: none;
}
/deep/ .arco-form-item-content {
  height: 100% !important;
}
</style>
